package com.s7.recycler.adapter;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import com.s7.recycler.R;
import com.s7.recycler.RecyclerCode;
import com.s7.recycler.holder.BaseHolder;
import com.s7.recycler.holder.BaseViewHolder;
import com.s7.recycler.holder.ErrorViewHolder;
import com.s7.recycler.holder.FooterViewHolder;
import com.s7.recycler.holder.LoadErrorHolder;
import com.s7.recycler.holder.LoadViewHolder;
import com.s7.recycler.holder.NullViewHolder;
import com.s7.recycler.listener.OnLoadingListener;
import com.s7.recycler.listener.Recycler;

import java.util.List;

/**
 * Created by Administor on 2018\7\10 0010.
 * RecyclerView 适配器--加载功能、空白页/错误页
 * 兼容Grid布局、Linear布局、StaggeredGrid布局
 */
public abstract class BaseLoadMoreAdapter<T> extends CompatRecyclerAdapter<T>  {

    @NonNull
    @Override
    public BaseHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == RecyclerCode.TYPE_ITEM) {
            View view = getView(parent, getLayoutId());
            return new BaseViewHolder(view);
        } else if (viewType == RecyclerCode.TYPE_NULL) {
            View view = getView(parent, getNullId());
            return new NullViewHolder(view);
        } else if (viewType == RecyclerCode.TYPE_LOAD) {
            View view = getView(parent, getLoadId());
            return new LoadViewHolder(view);
        } else if (viewType == RecyclerCode.TYPE_LOAD_ERROR) {
            View view = getView(parent, getLoadErrorId());
            return new LoadErrorHolder(view);
        } else if (viewType == RecyclerCode.TYPE_FOOTER) {
            View view = getView(parent, getFoodId());
            return new FooterViewHolder(view);
        } else {
            View view = getView(parent, getErrorId());
            return new ErrorViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull BaseHolder holder, int position) {

        holder.setRealPosition(position);

        /*
         * 绑定回调事件
         */
        initListener(holder);

        /*
         * 子类实现数据绑定
         */
        if (holder instanceof BaseViewHolder) {
            initClickListener((BaseViewHolder) holder, datas.get(position));
            ((BaseViewHolder) holder).setData(datas.get(position));
            bindData((BaseViewHolder) holder, position, datas.get(position));
        }

        /*
         * 当显示没有数据时
         */
        if (holder instanceof NullViewHolder) {
            bindNull((NullViewHolder) holder, position);
        }

        /*
         * 当显示底部时
         */
        if (holder instanceof FooterViewHolder) {
            bindFooter((FooterViewHolder) holder, position);
        }

        /*
         * 当显示加载更多时
         */
        if (holder instanceof LoadViewHolder) {
            bindLoad((LoadViewHolder) holder, position);
        }

        /*
         * 当显示加载更多失败时
         */
        if (holder instanceof LoadErrorHolder) {
            bindLoadError((LoadErrorHolder) holder, position);
        }

        /*
         * 当显示错误页面时
         */
        if (holder instanceof ErrorViewHolder) {
            bindError((ErrorViewHolder) holder, position);
        }
    }


    /**
     * 判断是否添加页面
     *
     * @return
     */
    @Override
    public int getItemCount() {
        if (isLegal() && !isFirst) {
            return datas == null ? 1 : datas.size() + 1;
        }
        return datas == null ? 0 : datas.size();
    }

    /**
     * 判断是否显示添加页
     *
     * @return
     */
    private boolean isLegal() {
        return (isLoad || isLoadError || isError || isFooter || isNull);
    }

    @Override
    public int getItemViewType(int position) {
        /*
         * 判断是否是联网错误
         */
        if (isError) {
            return RecyclerCode.TYPE_ERROR;
        }

        /*
         * 判断数据是否存在
         */
        if (!(datas.size() > 0) || isNull) {
            return RecyclerCode.TYPE_NULL;
        }

        /*
         * 是否有加载更多
         */
        if (isLoad && position + 1 == getItemCount()) {
            return RecyclerCode.TYPE_LOAD;
        }

        /*
         * 是否有加载失败
         */
        if (isLoadError && position + 1 == getItemCount()) {
            return RecyclerCode.TYPE_LOAD_ERROR;
        }

        /*
         * 是否没有更多
         */
        if (isFooter && position + 1 == getItemCount()) {
            return RecyclerCode.TYPE_FOOTER;
        }

        /*
         * 正常页面
         */
        return RecyclerCode.TYPE_ITEM;
    }

    /**
     *  GridLayoutManager 布局时
     *  当有 footer 时，设置 footer 占满屏幕宽度
     * @param recyclerView
     */
    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return isLast(position) ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    /**
     * StaggeredGridLayoutManager 布局时
     * 当有 footer 时，设置 footer 占满屏幕宽度
     * @param holder
     */
    @Override
    public void onViewAttachedToWindow(@NonNull BaseHolder holder) {
        super.onViewAttachedToWindow(holder);
        if (isStaggeredGridLayout(holder)) {
            handleLayoutIfStaggeredGridLayout(holder, holder.getLayoutPosition());
        }
    }

    /**
     * 判断当前布局是否是 StaggeredGridLayoutManager 布局
     * @param holder
     * @return
     */
    private boolean isStaggeredGridLayout(RecyclerView.ViewHolder holder) {
        ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
        if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
            return true;
        }
        if (layoutParams instanceof GridLayoutManager.LayoutParams) {
            return true;
        }
        return false;
    }

    /**
     * 判断 holder 是否是 footer（非正常Item）
     * 当 holder 为 footer 时，设置 holder 占满屏幕宽度
     * @param holder
     * @param position
     */
    private void handleLayoutIfStaggeredGridLayout(RecyclerView.ViewHolder holder, int position) {
        if (isLast(position)){
            ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
            if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
                ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
            }
        }
    }

    /**
     * 是否为 最后一个
     * @param position
     * @return
     */
    private boolean isLast(int position) {
        if (isAadditional) {
            if (datas == null) {
                return false;
            }

            if (datas.size() == 0) {
                return true;
            }

            if (position == datas.size()){
                return true;
            }
            return false;
        }
        return false;
    }


    /**
     * 获取子item
     *
     * @return
     */
    protected abstract int getLayoutId();

    /**
     * 获错误界面
     *
     * @return
     */
    protected int getErrorId() {
        return R.layout.recycler_error;
    }

    /**
     * 获取空页面
     *
     * @return
     */
    protected int getNullId() {
        return R.layout.recycler_null;
    }

    /**
     * 加载更多
     *
     * @return
     */
    protected int getLoadId() {
        return R.layout.recycler_load;
    }

    /**
     * 加载更多失败
     *
     * @return
     */
    protected int getLoadErrorId() {
        return R.layout.recycler_load_error;
    }

    /**
     * 没有更多
     *
     * @return
     */
    protected int getFoodId() {
        return R.layout.recycler_footer;
    }

    /**
     * 绑定数据
     *
     * @param holder 具体的viewHolder
     * @param data   当前Item的数据
     */
    protected abstract void bindData(BaseViewHolder holder, int position, T data);

    /**
     * 数剧为空时
     *
     * @param holder
     * @param position
     */
    protected void bindNull(NullViewHolder holder, int position) {

    }

    /**
     * 没有更多数据
     *
     * @param holder
     * @param position
     */
    protected void bindFooter(FooterViewHolder holder, int position) {

    }

    /**
     * 加载更多数据失败
     *
     * @param holder
     * @param position
     */
    protected void bindLoadError(LoadErrorHolder holder, int position) {

    }

    /**
     * 加载更多
     *
     * @param holder
     * @param position
     */
    protected void bindLoad(LoadViewHolder holder, int position) {

    }

    /**
     * 网络连接错误
     *
     * @param holder
     * @param position
     */
    protected void bindError(ErrorViewHolder holder, int position) {

    }

    private boolean isFirst = true; // 第一次显示数据（避免一进入界面就显示没有更多数据）
    private boolean isFooter = false; // 底部显示状态
    private boolean isAadditional = true; // 是否显示附加页面（错误页面/没有数据页面）
    private boolean isError = false; // 错误页面显示状态
    private boolean isNull = false; // 没有数据页面显示状态
    private boolean isLoad = true; // 加载显示状态
    private boolean isLoadError = false; // 加载失败显示状态
    private int num = 100;
    private OnLoadingListener loadingListener;

    /**
     * 是否显示底部
     * @param footer
     */
    public BaseLoadMoreAdapter setFooter(boolean footer) {
        isFooter = footer;
        return this;
    }

    /**
     * 是否显示附加页面（错误页、空白页等）
     * @param aadditional
     * @return
     */
    public BaseLoadMoreAdapter setAadditional(boolean aadditional) {
        isAadditional = aadditional;
        return this;
    }

    /**
     * 是否显示错误页面
     * @param error
     */
    public BaseLoadMoreAdapter setError(boolean error) {
        /*
         * 判断是否有附加页面（是否显示错误页面）
         */
        if (isAadditional) {
            isError = error;
        } else {
            isError = false;
        }
        isFirst = false;
        datas.clear();
        notifyDataSetChanged();
        return this;
    }

    /**
     * 是否显示没有数据页面
     * @param isNull
     */
    public BaseLoadMoreAdapter setNull(boolean isNull) {
        /*
         * 判断是否有附加页面（是否显示空页面）
         */
        if (isAadditional) {
            this.isNull = isNull;
        } else {
            this.isNull = false;
        }
        isFirst = false;
        datas.clear();
        notifyDataSetChanged();
        return this;
    }

    /**
     * 是否显示加载中
     *
     * @param load
     */
    public BaseLoadMoreAdapter setLoad(boolean load) {
        isLoad = load;
        return this;
    }

    /**
     * 是否显示加载失败
     *
     * @param loadError
     * @return
     */
    public BaseLoadMoreAdapter setLoadError(boolean loadError) {
        isLoadError = loadError;
        isLoad = !isLoadError;
        notifyDataSetChanged();
        return this;
    }

    /**
     * 每页最多显示的数量
     *
     * @param num
     */
    public BaseLoadMoreAdapter setPageSize(int num) {
        this.num = num;
        return this;
    }

    /**
     * 设置加载触发回调
     * @param loadingListener
     * @return
     */
    public BaseLoadMoreAdapter setLoadingListener(OnLoadingListener loadingListener) {
        this.loadingListener = loadingListener;
        return this;
    }

    /**
     * 绑定回调事件
     *
     * @param holder
     */
    protected void initListener(final BaseHolder holder) {

        /**
         * 加载更多失败
         */
        if (holder instanceof LoadErrorHolder) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    setLoadError(false);
                }
            });
        }

        /**
         * 加载更多
         */
        if (holder instanceof LoadViewHolder) {
            if (loadingListener != null) {
                loadingListener.onLoading();
            }
        }

        /**
         * 加载失败，重新加载
         */
        if (holder instanceof ErrorViewHolder) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (loadingListener != null) {
                        loadingListener.onReload();
                    }
                }
            });
        }
    }

    /**
     * 刷新数据（第一次加载数据）
     *
     * @param datas
     */
    public void onRefresh(List<T> datas) {
        isFirst = false;
        isError = false;
        initData();
        this.datas.clear();
        if (datas != null) {
            this.datas.addAll(datas);
        }
        isNull(this.datas);
        isLoad(this.datas);

        notifyDataSetChanged();
    }

    /**
     * 判断是否显示空白页
     */
    private void isNull(List<T> datas) {
        /**
         * 显示附加页面时，判断页面是否为空
         */
        if (isAadditional) {
            if (!(datas != null && datas.size() > 0)) {
                isNull = true;
            } else {
                isNull = false;
            }
        } else {
            isNull = false;
        }
    }

    /**
     * 判断是否有更多数据
     */
    private void isLoad(List<T> datas) {
        /**
         * 将加载失败关闭
         */
        isLoadError = false;
        if (datas != null && datas.size() % num == 0 && datas.size() > 0) {
            isLoad = true;
        } else {
            isLoad = false;
        }
    }

    /**
     * 添加数据
     * @param datas
     */
    public void add(List<T> datas) {
        isLoad(datas);
        isNull(datas);
        initData();
        if (datas != null) {
            this.datas.addAll(datas);
            notifyItemRangeInserted(getSize(), datas.size());
        }
    }

    /**
     * 删除指定位置的内容
     * 当集合为空时显示空白页
     *
     * @param position
     */
    public void remove(int position) {
        if (datas != null && position < this.datas.size()) {
            this.datas.remove(position);
            if (!(this.datas.size() > 0)) {
                isNull = true;
            }
            notifyDataSetChanged();
        }
    }

}
